package com.hhkj.admin.bank.service.biz.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hhkj.admin.bank.common.component.checker.RuleChecker;
import com.hhkj.admin.bank.common.component.creator.RuleCreator;
import com.hhkj.admin.bank.common.component.supplier.RuleSupplier;
import com.hhkj.admin.bank.domain.Bank;
import com.hhkj.admin.bank.domain.BankRule;
import com.hhkj.admin.bank.model.dopo.BankRuleDo;
import com.hhkj.admin.bank.model.dopo.BankRulePo;
import com.hhkj.admin.bank.model.req.BankRuleReq;
import com.hhkj.admin.bank.model.res.BankRuleRes;
import com.hhkj.admin.bank.service.base.BankRuleService;
import com.hhkj.admin.bank.service.base.BankService;
import com.hhkj.admin.bank.service.biz.BankBizService;
import com.hhkj.admin.bank.service.biz.BankRuleBizService;
import com.hhkj.admin.bank.service.extend.BankRuleExtendService;
import com.ruoyi.common.base.biz.service.biz.BaseBizServiceImpl;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.exception.GlobalException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * BankRuleBizServiceImpl
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/6/8 14:45
 */
@Service
public class BankRuleBizServiceImpl
        extends BaseBizServiceImpl<BankRule, BankRuleReq, BankRuleRes,
        BankRuleDo, BankRulePo, BankRuleService, BankRuleExtendService>
        implements BankRuleBizService
{
    @Autowired
    private RuleSupplier supplier;
    @Autowired
    private RuleChecker checker;
    @Autowired
    private BankBizService bankBizService;
    @Autowired
    private BankService bankService;

    @Override
    public BankRuleRes getByCourseParentIdAndCourseBankTypeId(Long courseParentId, Long courseBankTypeId)
    {
        BankRule rulePo = this.getExtendService().getPoByCourseParentIdAndCourseBankTypeId(courseParentId, courseBankTypeId);
        BankRuleRes result = BeanUtil.toBean(rulePo, BankRuleRes.class);
        if (ObjectUtil.isNotNull(result)) {
            supplier.supplyChildren(result);
        }
        return result;
    }

    @Override
    protected void beforePage(BankRuleReq req)
    {
        req.setCourseFlag(SysConst.Flag.IS.getFlag());
        super.beforePage(req);
    }

    /**
     * 分页列表
     *
     * @param resList 列表数据
     */
    @Override
    protected void afterPage(List<BankRuleRes> resList)
    {
        // 批量补充下一级规则列表信息
        supplier.supplyBatchChildren(resList);
        supplier.supplyExistUnConfigCourse(resList);
    }

    @Override
    protected void afterGetById(BankRuleRes bankRuleRes)
    {
        supplier.supplyCourseChildren(bankRuleRes);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(BankRuleReq req)
    {
        // 兼容前端请求带id配置
        if (ObjectUtil.isNotNull(req.getId())) {
            return this.update(req);
        }
        this.beforeSave(req);
        boolean result = this.getService().save(req);
        if (result) {
            this.afterSave(req);
        }
        return result;
    }

    /**
     * 新增前置方法
     *
     * @param req 题库规则
     */
    @Override
    protected void beforeSave(BankRuleReq req)
    {
        // 1、对应类别是否存在
        checker.checkCourseParent(req.getCourseParentId());
        // 2、查看课程的类别信息是否存在
        checker.checkCourseBankType(req.getCourseParentId(), req.getCourseBankTypeId());
        // 3、如果是统一配置，校验对应数值信息
        checker.checkChildren(req);
        // 4、删除相关题库配置信息
        this.getExtendService().removeByCourseParentIdAndCourseBankTypeId(req.getCourseParentId(), req.getCourseBankTypeId());
    }

    /**
     * 新增后置方法
     *
     * @param req 题库规则
     */
    @Override
    protected void afterSave(BankRuleReq req)
    {
        this.saveChildren(req);
        // 校验并上线新题库信息
        bankBizService.updateBankByRule(req);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(BankRuleReq req)
    {
        this.beforeUpdate(req);
        boolean result = this.getService().updateById(req);
        if (result) {
            this.afterUpdate(req);
        }
        return result;
    }

    /**
     * 修改后置规则信息
     *
     * @param req 抽题规则信息
     */
    @Override
    protected void afterUpdate(BankRuleReq req)
    {
        this.saveChildren(req);
        // 校验并上线新题库信息
        bankBizService.updateBankByRule(req);
    }

    /**
     * 保存子选题规则信息
     *
     * @param req 主要选题规则信息
     */
    private void saveChildren(BankRuleReq req)
    {
        List<BankRule> children = RuleCreator.createChildren(req);
        if (CollectionUtil.isNotEmpty(children)) {
            this.getService().saveBatch(children);
            req.setChildren(BeanUtil.copyToList(children, BankRuleReq.class));
        }
    }

    /**
     * 修改前置功能
     *
     * @param bankRule 抽题规则信息
     */
    @Override
    protected void beforeUpdate(BankRuleReq bankRule)
    {
        // 1、如果是统一配置，校验对应数值信息
        checker.checkChildren(bankRule);
        // 2、删除对应的下级规则配置
        this.getExtendService().removeByParentId(bankRule.getId());
    }

    @Override
    protected void beforeRemove(List<Long> idList)
    {
        // 获取对应子规则id
        LambdaQueryWrapper<BankRule> ruleQuery = new LambdaQueryWrapper<>();
        ruleQuery.in(BankRule::getParentId, idList);
        List<Long> childrenIdList = this.getService().list(ruleQuery)
                .stream().map(BankRule::getId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(childrenIdList)) {
            idList.addAll(childrenIdList);
        }
        // 查看是否有对应的题库信息
        LambdaQueryWrapper<Bank> bankQuery = new LambdaQueryWrapper<>();
        bankQuery.in(Bank::getRuleId, idList);
        bankQuery.eq(Bank::getPublishFlag, SysConst.Flag.IS.getFlag());
        long publishBankAmount = bankService.count(bankQuery);
        if (publishBankAmount > 0L) {
            throw new GlobalException("该规则有上架题库信息，无法删除");
        }
    }
}
